package zhongbo.java.fast.order.service.impl;

import com.google.common.util.concurrent.AtomicDouble;
import zhongbo.java.fast.order.ItemBuilder;
import zhongbo.java.fast.order.enums.ItemType;
import zhongbo.java.fast.order.enums.OrderStatus;
import zhongbo.java.fast.order.exception.BusinessException;
import zhongbo.java.fast.order.exception.ExceptionCode;
import zhongbo.java.fast.order.model.Item;
import zhongbo.java.fast.order.model.Order;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class OrderServiceImpl implements zhongbo.java.fast.order.service.IOrderService {

    // 创建订单（核心方法）
    public Order createOrder(List<Item> items, boolean isVIP) {
        // TODO 实现业务规则校验与价格计算
        return createOrder(items, isVIP, LocalDateTime.now());
    }

    // 取消订单
    public void cancelOrder(String orderId) {
        // TODO 实现状态校验与超时处理
        cancelOrder(orderId, LocalDateTime.now());
    }

    @Override
    public Order createOrder(List<Item> items, boolean isVIP, LocalDateTime currentTime) throws BusinessException {
        if (currentTime == null) {
            currentTime = LocalDateTime.now();
        }
//        开始
        Order order = new Order();
        order.setStatus(OrderStatus.CREATED);
        AtomicDouble totalPrice = new AtomicDouble(0);
//↓
//[检查商品列表是否为空?]
//→ 空 → 抛出"订单不能为空"异常 → 结束
        if (items == null || items.isEmpty()) {
            throw new BusinessException(ExceptionCode.EMPTY);
        }
//→ 非空 → [是否包含主食?]
//          → 否 → 抛出"必须包含主食"异常 → 结束
        long countMainFood = items.stream().filter(item -> ItemType.MAIN.equals(item.getType())).count();
        long countDessertFood = items.stream().filter(item -> ItemType.DESSERT.equals(item.getType())).count();
        long countDrinkFood = items.stream().filter(item -> ItemType.DRINK.equals(item.getType())).count();
//          → 是 → [是否有甜品且无主食?]
//                  → 是 → 抛出"甜品不能单独购买"异常 → 结束
        ///////// ↑已有主食判断, 这里调整两个判断顺序, 优先判断甜品
        if (countDessertFood > 0 && countMainFood == 0) {
            throw new BusinessException(ExceptionCode.DESSERT_ALONE);
        }
        if (countMainFood == 0) {
            throw new BusinessException(ExceptionCode.MAIN_FOOD);
        }
//                  → 否 → [检查冰咖啡时间（15点后禁止）?]
//                          → 是 → 移除冰咖啡并添加提示 → 继续
//                          → 否 → 继续
        long countIceCaffe = items.stream().filter(item -> "冰咖啡".equals(item.getName())).count();
        int hour = currentTime.getHour();
        if (countIceCaffe > 0 && hour >= 15) {
            // 这个逻辑需要前置,待考虑 [移除类]
            order.appendRemark("15点后禁止, 移除冰咖啡");
            // 移除冰咖啡
            items = items.stream().filter(item -> "冰咖啡".equals(item.getName())).collect(Collectors.toList());
        }
//                          ↓
//                     [应用促销规则]
//        开始
//↓
//[检查是否满足套餐条件（汉堡+薯条）?]
//→ 是 → 替换为套餐价25元 → 结束本流程
        List<String> package1 = Arrays.asList("汉堡", "薯条");
        List<String> itemNames = items.stream().map(Item::getName).collect(Collectors.toList());
        // 名字去重
        Set<String> nameSet = new HashSet<>(itemNames);
        if (itemNames.size() == package1.size() && itemNames.size() == nameSet.size()) {
            // 是否包含汉堡和薯条
            if (package1.containsAll(nameSet)) {
                // 是套餐, 直接返回
                order.setItems(items);
                order.setTotalPrice(25);
                return order;
            }
        }
//→ 否 → [检查是否有两杯同款饮料?]
//        → 是 → 第二杯半价 → 继续
        // 按商品分组统计数量
        // key: itemId, value: count
        if (countDrinkFood > 0) {
            Map<String, Long> drinkCounts = items.stream()
                    .filter(i -> i.getType() == ItemType.DRINK)
                    .collect(Collectors.groupingBy(Item::getId, Collectors.counting()));
            drinkCounts.forEach((id, count) -> {
                // 每2杯有1杯半价
                int fullPriceCups = (int) (count / 2);
                // 剩下不够2杯的, 余下1杯全价
                int halfPriceCups = (int) (count % 2);
                double drinkPrice = (fullPriceCups * 1.5 * getPriceById(id)) + (halfPriceCups * getPriceById(id));
                totalPrice.addAndGet(drinkPrice);
            });
        }
//        → 否 → [总价>100且非周末?]
//                → 是 → 满减10元 → 继续
        // 获取星期几, 1-7
        int dayOfWeek = currentTime.getDayOfWeek().getValue();
        boolean isFullMinus = totalPrice.get() >= 100 && dayOfWeek != 7;
        if (isFullMinus) {
            totalPrice.addAndGet(-10);
        }
//                → 否 → [是否是VIP用户?]
//                        → 是 → 总价×0.9 → 结束
        if (isVIP) {
            totalPrice.set(totalPrice.get() * 0.9);
        }
//                        → 否 → 结束
//                          ↓
//                     [商品数量≤5?]
//                          → 否 → 抛出"商品数量超限"异常 → 结束
//                          → 是 → 生成订单 → 结束
        if (order.getItems().size() >= 5) {
            throw new BusinessException("商品数量超限", ExceptionCode.TOO_MANY_ITEMS);
        }
        return order;
    }

    private double getPriceById(String id) {
        List<Item> allItems = ItemBuilder.allItems();
        for (Item allItem : allItems) {
            if (allItem.getId().equals(id)) {
                return allItem.getPrice();
            }
        }
        throw new BusinessException("商品不存在, id: " + id, ExceptionCode.ERROR);
    }

    @Override
    public void cancelOrder(String orderId, LocalDateTime currentTime) throws BusinessException {

    }
}